/**
 * 给定01矩阵，求最大的以1位边框的正方形
 * N、M在1000，需要一个O(N^2logN)的算法
 * 首先用O(N^2)的时间对每个点(i, j)求出其向下向右最长1的数量
 * 然后for每个(i,j):
 *     令k=min(右, 下)
 *     这是该点为左上点的最大可能答案
 *     然后依次减减查看答案即可
 * 时间复杂度应该到不了O(N^3)，但是不知道是多少
 * 树形DP有一种情况，看起来是O(N^2)，实际上是O(N)的
 */
#include <bits/stdc++.h>
using namespace std;

#include <bits/extc++.h>
using namespace __gnu_pbds;

using Real = long double;
using llt = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;

int const SHA = 0;
int const XIA = 1;
int const ZUO = 2;
int const YOU = 3;

int N, M;
vvi A;
vector<vector<array<int, 4>>> D;


int proc(){
    D.assign(N + 2, vector<array<int, 4>>(M + 2, {0, 0, 0, 0}));
    vvi U(N + 2, vi(N + 2, 0));
    vvi V(N + 2, vi(N + 2, 0));
    for(int i=1;i<=N;++i){
        for(int j=1;j<=M;++j){
            if(0 == A[i][j]) continue;
            U[i][j] = min(D[i][j][SHA] = D[i - 1][j][SHA] + 1, D[i][j][ZUO] = D[i][j - 1][ZUO] + 1);
        }
    }
    for(int i=N;i>=1;--i)for(int j=M;j>=1;--j){
        if(0 == A[i][j]) continue;
        V[i][j] = min(D[i][j][XIA] = D[i + 1][j][XIA] + 1, D[i][j][YOU] = D[i][j + 1][YOU] + 1);
    }

    int ans = 0;
    for(int i=1;i+ans<=N;++i){
        for(int j=1;j+ans<=N;++j){
            int k = V[i][j];
            while(k > ans){
                if(D[i+k-1][j][YOU] >= k and D[i][j+k-1][XIA] >= k){
                    ans = k;
                    break;
                }
                --k;
            }    
        }
    }

    return ans;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(0);
    int nofkase = 1;
    // cin >> nofkase;
    while(nofkase--){
        cin >> N >> M;
        A.assign(N + 2, vi(M + 2, 0));
        for(int i=1;i<=N;++i)for(int j=1;j<=M;++j)cin>>A[i][j];
        cout << proc() << endl;
    }
    return 0;
}